package com.ywl.exercise.dao;

import java.lang.reflect.Type;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.jdbc.Work;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

import com.ywl.exercise.entity.GameEntity;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;

public class BaseDao<T> {

	@Autowired
	private SessionFactory sessionFactory;

	private Class<T> entityClass;

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public BaseDao() {
		Type genType = getClass().getGenericSuperclass();
		Type[] param = ((ParameterizedType) genType).getActualTypeArguments();
		entityClass = (Class) param[0];

	}

	private Session getSession() {
		return sessionFactory.getCurrentSession() == null ? sessionFactory
				.openSession() : sessionFactory.getCurrentSession();
	}

	@SuppressWarnings("unchecked")
	public T load(Serializable id) {
		return (T) getSession().load(entityClass, id);
	}

	@SuppressWarnings("unchecked")
	public T get(Serializable id) {
		return (T) getSession().get(entityClass, id);

	}

	public void save(T entity) {
		getSession().save(entity);
	}

	public void update(T entity) {
		getSession().saveOrUpdate(entity);
	}

	public void delete(T entity) {
		getSession().delete(entity);
	}

	@SuppressWarnings("rawtypes")
	public List getBySQLQuery(String sql) {
		Query query = getSession().createSQLQuery(sql);
		return query.list();
	}

	/**
	 * 创建Query对象.
	 * 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
	 * 留意可以连续设置,如下：
	 * 
	 * <pre>
	 * dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
	 * </pre>
	 * 
	 * 调用方式如下：
	 * 
	 * <pre>
	 *        dao.createQuery(hql)
	 *        dao.createQuery(hql,arg0);
	 *        dao.createQuery(hql,arg0,arg1);
	 *        dao.createQuery(hql,new Object[arg0,arg1,arg2])
	 * </pre>
	 * 
	 * @param values
	 *            可变参数.
	 */
	public Query createQuery(String hql, Object... values) {
		Assert.hasText(hql);
		Query query = getSession().createQuery(hql);
		for (int i = 0; i < values.length; i++) {
			query.setParameter(i, values[i]);
		}
		return query;
	}

	/**
	 * 对数据进行分页
	 */
	@SuppressWarnings("unchecked")
	public List<T> getObjects(int pageSize, int currentPage, String hql) {
		Query query = getSession().createQuery(hql);
		query.setMaxResults(pageSize);
		query.setFirstResult(currentPage);
		return query.list();
	}

	/**
	 * 获取数据的总数
	 */
	public int findAllCount(String hql) {
		Query q = getSession().createQuery(hql);
		return q.list().size();
	}
	
	
	public int get(final String hql,final GameEntity entity) throws SQLException {
		//1、获取connection
		getSession().doWork(new Work() {
			@Override
			public void execute(Connection connection) throws SQLException {
				//2、sql 执行 存储过程的名称 
				CallableStatement callableStatement = connection.prepareCall(hql);
				//3、传入输入参数
				callableStatement.setString(1, entity.getLoginid());
				callableStatement.setInt(2, entity.getScores());
				//4、处理 输出参数  注册输出参数 
				callableStatement.registerOutParameter(3, Types.INTEGER);
				int rowAffected = callableStatement.executeUpdate();
				if(rowAffected > 0) {
					//获取输出参数
					entity.setGameid(callableStatement.getInt(3));
				}
			}
		});
		return entity.getGameid();
	}
}
